package jnpf.engine.util.xml;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import jnpf.engine.custom.exception.UnSupportExpressionException;
import jnpf.util.StringUtil;
import org.springframework.expression.spel.SpelParseException;
import org.springframework.expression.spel.ast.OpAnd;
import org.springframework.expression.spel.ast.OpOr;
import org.springframework.expression.spel.ast.SpelNodeImpl;
import org.springframework.expression.spel.standard.SpelExpressionParser;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 流程引擎条件表达式解析器 目前支持单线程串行调用
 */
public class SimpleSpELToProperCondParser {

	private static final Map<String, String> parenMap = new HashMap<>();

	private static final String REF_PREFIX = "ref";

	private static final String REF_EQ = "==";

	private static final SpelExpressionParser parser = new SpelExpressionParser();

	private static final Snowflake snowflake = IdUtil.getSnowflake();


	public static void main(String[] args) {
		String expression = "(amount > 500 || amount < 800 && status == 'PENDING')  || amount < 1000 || (isActive == true || status == 'PENDING')";
		Boolean complex = SpElUtil.isComplex(expression);
		List<ProperCond> properConds = SimpleSpELToProperCondParser.parseSimpleExpressionToProperCond(expression);
		System.out.println(JSONObject.toJSONString(properConds));
	}

	/**
	 * 解析和处理表达式
	 *
	 * @param expression
	 * @return
	 */
	protected static List<ProperCond> parseSimpleExpressionToProperCond(String expression) {
		//()处理
		expression = parseParen(expression);
		// 表达式解析
		try {
			// 解析表达式为 AST 节点
			SpelNodeImpl rootNode = (SpelNodeImpl) parser.parseRaw(expression).getAST();
			// 初始logic
			String initLogic = getLogic(rootNode);
			// 提取表达式为 ProperCond
			List<ProperCond> properConds = extractProperCondList(rootNode, initLogic);
			// 清除表达式缓存
			parenMap.clear();
			return properConds;
		} catch (SpelParseException e) {
			throw new UnSupportExpressionException("表达式解析失败: " + expression, e);
		}
	}

	/**
	 * 提取表达式中的() 并 验证是否有多层嵌套
	 *
	 * @param s
	 * @return
	 */
	private static String parseParen(String s) {
		int li = s.indexOf("(");
		int ri = s.indexOf(")");
		if (li == -1 && ri == -1) {
			return s;
		}
		if (li == -1 || ri == -1) {
			throw new UnSupportExpressionException("表达式解析失败: " + s);
		}
		String parenStr = s.substring(li, ++ri);
		parenMap.put(String.valueOf(li), parenStr);
		// 替换表达式
		String replaceStr = REF_PREFIX + REF_EQ + li;
		return parseParen(s.replace(parenStr, replaceStr));
	}


	/**
	 * 处理逻辑分支表达式
	 *
	 * @param node
	 * @param logic
	 * @return
	 */
	private static List<ProperCond> extractProperCondList(SpelNodeImpl node, String logic) {
		List<ProperCond> properCondList = new ArrayList<>();
		if (!(node instanceof OpOr) && !(node instanceof OpAnd)) {
			ProperCond properCond = new ProperCond();
			properCond.setLogic(logic);
			properCond.setId(snowflake.nextId());
			properCond.setGroups(extractGroupModel(node));
			properCondList.add(properCond);
			return properCondList;
		}
		for (int i = 0; i < node.getChildCount(); i++) {
			SpelNodeImpl child = (SpelNodeImpl) node.getChild(i);
			String childLogic = getLogic(child);
			properCondList.addAll(extractProperCondList(child, childLogic));
		}
		return properCondList;
	}

	/**
	 * 获取上级logic逻辑符
	 *
	 * @param node
	 * @return
	 */
	private static String getLogic(SpelNodeImpl node) {
		if (ObjectUtil.isNull(node)) {
			return "&&";
		}
		if (node instanceof OpAnd) {
			return "&&";
		}
		if (node instanceof OpOr) {
			return "||";
		}
		return getLogic(getParent(node));
	}

	/**
	 * 获取上级节点
	 *
	 * @param node
	 * @return
	 */
	private static SpelNodeImpl getParent(SpelNodeImpl node) {
		Class clazz = SpelNodeImpl.class;
		try {
			Field parent = clazz.getDeclaredField("parent");
			parent.setAccessible(true);
			return (SpelNodeImpl) parent.get(node);
		} catch (NoSuchFieldException | IllegalAccessException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 处理条件分支表达式 非 逻辑分支
	 *
	 * @param node
	 * @return
	 */
	private static List<ProperCond.GroupsModel> extractGroupModel(SpelNodeImpl node) {
		List<ProperCond.GroupsModel> res = new ArrayList<>();
		ProperCond.GroupsModel group = new ProperCond.GroupsModel();
		if (node.getChildCount() == 2) {
			// 二元表达式，例如 amount > 100
			group.setField(node.getChild(0).toStringAST().trim()); // 获取字段
			group.setOperator(getOperatorFromNode(node));  // 获取操作符
			group.setValue(node.getChild(1).toStringAST().trim()); // 获取值
		} else if (node.getChildCount() == 1) {
			// 单独的变量，例如 isActive
			group.setField(node.getChild(0).toStringAST().trim()); // 只有字段
		}
		// 处理逻辑表达式
		group.setLogic(getLogic(node));
		// 处理()内表达式
		if (group.getField().equals(REF_PREFIX) && parenMap.containsKey((String) group.getValue())) {
			String parenStr = parenMap.get((String) group.getValue());
			if (StringUtil.isEmpty(parenStr)) {
				return res;
			}
			try {
				// 解析表达式为 AST 节点
				SpelNodeImpl rootNode = (SpelNodeImpl) parser.parseRaw(parenStr).getAST();
				// 初始logic
				String initLogic = getLogic(rootNode);
				// 处理子表达式
				res.addAll(extractMapGroups(rootNode, initLogic));
			} catch (SpelParseException e) {
				throw new UnSupportExpressionException("表达式解析失败: " + parenStr, e);
			}
		} else {
			res.add(group);
		}
		return res;
	}

	/**
	 * 处理嵌套的()中的表达式
	 *
	 * @param node
	 * @param logic
	 * @return
	 */
	private static List<ProperCond.GroupsModel> extractMapGroups(SpelNodeImpl node, String logic) {
		List<ProperCond.GroupsModel> res = new ArrayList<>();
		if (!(node instanceof OpOr) && !(node instanceof OpAnd)) {
			res.addAll(extractGroupModel(node));
			return res;
		}
		for (int i = 0; i < node.getChildCount(); i++) {
			SpelNodeImpl child = (SpelNodeImpl) node.getChild(i);
			String childLogic = child instanceof OpAnd ? "&&" : "||";
			res.addAll(extractMapGroups(child, childLogic));
		}
		return res;
	}

	/**
	 * 获取操作符
	 * @param node
	 * @return
	 */
	private static String getOperatorFromNode(SpelNodeImpl node) {
		// 精确获取操作符
		if (node instanceof OpAnd) {
			return "&&";
		} else if (node instanceof OpOr) {
			return "||";
		}
		// 处理其他运算符，例如 `==`, `>`, `<`
		String nodeString = node.toStringAST().trim();
		// 提取操作符 (注意：只取中间的运算符)
		if (nodeString.contains(">")) {
			return ">";
		} else if (nodeString.contains("<")) {
			return "<";
		} else if (nodeString.contains("==")) {
			return "==";
		} else if (nodeString.contains("!=")) {
			return "!=";
		}
		return nodeString; // 默认为原字符串
	}

}